package com.winit.requirement.repository;

import com.winit.requirement.model.BrdRequirement;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.persistence.Column;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Component
public class BrdRequirementRepositoryOperation {

    private static Logger log = LoggerFactory.getLogger(BrdRequirementRepositoryOperation.class);

    @PersistenceContext
    private EntityManager entityManager;

    @Transactional
    public int updateBrdRequirementById(BrdRequirement brdRequirement) {
        BrdRequirement entity = entityManager.find(BrdRequirement.class, brdRequirement.getReqId());
        if (entity == null) {
            return 0;
        }
        boolean update = false;
        if (brdRequirement.getBrdId() != null) {
            update = true;
            entity.setBrdId(brdRequirement.getBrdId());
        }

        if (brdRequirement.getReqCreateTime() != null) {
            update = true;
            entity.setReqCreateTime(brdRequirement.getReqCreateTime());
        }

        if (brdRequirement.getProjectPlanId() != null){
            update = true;
            entity.setProjectPlanId(brdRequirement.getProjectPlanId());
        }

        if (brdRequirement.getReqChargerAccount() != null) {
            update = true;
            entity.setReqChargerAccount(brdRequirement.getReqChargerAccount());
        }

        if (brdRequirement.getReqChargerRealname() != null) {
            update = true;
            entity.setReqChargerRealname(brdRequirement.getReqChargerRealname());
        }

        if (brdRequirement.getReqCreaterAccount() != null) {
            update = true;
            entity.setReqCreaterAccount(brdRequirement.getReqCreaterAccount());
        }

        if (brdRequirement.getReqCreaterRealname() != null) {
            update = true;
            entity.setReqCreaterRealname(brdRequirement.getReqCreaterRealname());
        }

        if (brdRequirement.getReqDesc() != null) {
            update = true;
            entity.setReqDesc(brdRequirement.getReqDesc());
        }

        if (brdRequirement.getReqIsDel() != null) {
            update = true;
            entity.setReqIsDel(brdRequirement.getReqIsDel());
        }

        if (brdRequirement.getReqName() != null) {
            update = true;
            entity.setReqName(brdRequirement.getReqName());
        }

        if (brdRequirement.getReqStatus() != null) {
            update = true;
            entity.setReqStatus(brdRequirement.getReqStatus());
        }

        if (brdRequirement.getReqUseTime() != null) {
            update = true;
            entity.setReqUseTime(brdRequirement.getReqUseTime());
        }
        if (brdRequirement.getReqDataInition() != null) {
            update = true;
            entity.setReqDataInition(brdRequirement.getReqDataInition());
        }
        if (brdRequirement.getReqFunctionDesc() != null) {
            update = true;
            entity.setReqFunctionDesc(brdRequirement.getReqFunctionDesc());
        }
        if (brdRequirement.getReqLegacyDataDispose() != null) {
            update = true;
            entity.setReqLegacyDataDispose(brdRequirement.getReqLegacyDataDispose());
        }
        if (brdRequirement.getReqOnlineConfigRequirement() != null) {
            update = true;
            entity.setReqOnlineConfigRequirement(brdRequirement.getReqOnlineConfigRequirement());
        }
        if (brdRequirement.getReqPreCondition() != null) {
            update = true;
            entity.setReqPreCondition(brdRequirement.getReqPreCondition());
        }
        if (brdRequirement.getReqPriority() != null) {
            update = true;
            entity.setReqPriority(brdRequirement.getReqPriority());
        }
        if (brdRequirement.getReqNote() != null) {
            update = true;
            entity.setReqNote(brdRequirement.getReqNote());
        }
        if (brdRequirement.getIssues() != null) {
            update = true;
            entity.setIssues(brdRequirement.getIssues());
        }
        if (brdRequirement.getProductLineId() != null) {
            update = true;
            entity.setProductLineId(brdRequirement.getProductLineId());
        }
        if (brdRequirement.getFeatures() != null) {
            update = true;
            entity.setFeatures(brdRequirement.getFeatures());
        }

        if (brdRequirement.getFlows() != null) {
            update = true;
            entity.setFlows(brdRequirement.getFlows());
        }

        if(brdRequirement.getReqUpdateAccount()!=null){
            update =true;
            entity.setReqUpdateAccount(brdRequirement.getReqUpdateAccount());
        }

        if(brdRequirement.getReqUpdateRealname()!=null){
            entity.setReqUpdateRealname(brdRequirement.getReqUpdateRealname());
        }

        entity.setReqUpdateTime(new Date());

        if (!update) {
            return 0;
        }
        entityManager.merge(entity);
        entityManager.flush();
        return 1;
    }



    public List<BrdRequirement> getBrdRequirements(String brdId, String projectPlanId, String reqId, String productLineId, String status, String chargerAccount, String keyword, String excludeIsDel,String startDate,String online){

        String sql = "select mr.*, mb.brd_name, mpp.project_plan_name from matrix_requirements mr LEFT JOIN matrix_brd mb ON mr.brd_id = mb.brd_id LEFT JOIN matrix_project_plan mpp ON  mr.project_plan_id = mpp.project_plan_id" +
//        String sql = "select mr.* from matrix_requirements mr " +
                " where 1=1 AND( :brdId is null or mr.brd_id=:brdId ) AND( :projectPlanId is null or mr.project_plan_id=:projectPlanId ) " +
                " AND( :reqId is null or mr.req_id=:reqId ) AND( :productLineId is null or mr.product_line_id=:productLineId ) " +
                " AND( :status is null or mr.req_status=:status ) AND( :chargerAccount is null or mr.req_charger_account=:chargerAccount ) " +
                " AND ( :keyword is null or (mr.req_no = :keyword OR mr.req_name LIKE concat('%', :keyword, '%') OR mr.req_desc LIKE concat('%', :keyword, '%'))) " +
                " AND (mr.req_is_del <> :excludeIsDel) " +
                " AND (:startDate is null or mr.req_create_time >= :startDate)" +
                " AND (:online IS NOT NULL or (mr.req_status!= 'COMPLETED')) order by mr.req_create_time desc";

        Query query = entityManager.createNativeQuery(sql).setParameter("brdId", brdId).setParameter("projectPlanId", projectPlanId).setParameter("reqId", reqId)
                .setParameter("productLineId", productLineId).setParameter("status", status).setParameter("chargerAccount", chargerAccount)
                .setParameter("keyword", keyword).setParameter("excludeIsDel", excludeIsDel).setParameter("startDate",startDate).setParameter("online",online);
//        query.getHints()
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<?> lst = query.getResultList();
        return this.convertValueForGetBrdRequirements1(lst);
    }


    private List<BrdRequirement> convertValueForGetBrdRequirements1(List lst){
        List<BrdRequirement> newLst = new ArrayList<BrdRequirement>();
        if (CollectionUtils.isEmpty(lst)){
            return newLst;
        }
        for (Map<String, Object> map : (List<Map<String, Object>>)lst){
            BrdRequirement brdRequirement = new BrdRequirement();
            newLst.add(brdRequirement);
            brdRequirement.setBrdName((String)map.get("brd_name"));
            brdRequirement.setProjectPlanName((String)map.get("project_plan_name"));
            for(Field field : BrdRequirement.class.getDeclaredFields()){
                field.setAccessible(true);
                Column annotation = field.getAnnotation(Column.class);
                try {
                    Object value = null == annotation ? map.get(field.getName()) : map.get(annotation.name());
                    if (null == value){
                        continue;
                    }
                    ConversionService conversionService = DefaultConversionService.getSharedInstance();
                    if (!value.getClass().isAssignableFrom(field.getType())){
                        if (conversionService.canConvert(value.getClass(), field.getType())){
                            value = conversionService.convert(value, field.getType());
                        }else {
                            log.error("不支持的转换类型:" + value.getClass() + "-" + field.getType());
                        }
                    }
                    field.set(brdRequirement, value);
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
        return newLst;
    }
}
